

package com.platform.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 日期处理
 *
 * @author
 */
@Slf4j
public class DateUtils {
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * 无分隔符日期格式 "yyyyMMddHHmmssSSS"
     */
    public static String DATE_TIME_PATTERN_YYYY_MM_DD_HH_MM_SS_SSS = "yyyyMMddHHmmssSSS";
    /**
     * 不带秒的标准日期格式 "yyyy.MM.dd HH:mm"
     */
    public static String PATTERN_YYYY_MM_DD_HH_MM = "yyyy.MM.dd HH:mm";
    /**
     * 无分隔符日期格式 "yyyyMMddHHmmss"
     */
    public static String DATE_TIME_PATTERN_YYYY_MM_DD_HH_MM_SS = "yyyyMMddHHmmss";
    /**
     * 无分隔符日期格式 "yyyyMMdd"
     */
    public static String DATE_TIME_PATTERN_YYYY_MM_DD = "yyyyMMdd";

    // 日期转换格式数组
    public static String[][] regularExp = new String[][]{

            // 默认格式
            {"\\d{4}-((([0][1,3-9]|[1][0-2]|[1-9])-([0-2]\\d|[3][0,1]|[1-9]))|((02|2)-(([1-9])|[0-2]\\d)))\\s+([0,1]\\d|[2][0-3]|\\d):([0-5]\\d|\\d):([0-5]\\d|\\d)",
                    DATE_TIME_PATTERN},
            // \
            {"\\d{4}-((([0][1,3-9]|[1][0-2]|[1-9])/([0-2]\\d|[3][0,1]|[1-9]))|((02|2)/(([1-9])|[0-2]\\d)))\\s+([0,1]\\d|[2][0-3]|\\d):([0-5]\\d|\\d):([0-5]\\d|\\d)",
                    DATE_TIME_PATTERN},
            // 仅日期格式 年月日 时 分 秒
            {"\\d{4}.((([0][1,3-9]|[1][0-2]|[1-9]).([0-2]\\d|[3][0,1]|[1-9]))|((02|2).(([1-9])|[0-2]\\d)))\\s+([0,1]\\d|[2][0-3]|\\d):([0-5]\\d|\\d)",
                    PATTERN_YYYY_MM_DD_HH_MM},
            // 仅日期格式 年月日
            {"\\d{4}-((([0][1,3-9]|[1][0-2]|[1-9])-([0-2]\\d|[3][0,1]|[1-9]))|((02|2)-(([1-9])|[0-2]\\d)))",
                    DATE_PATTERN},
            //  带毫秒格式
            {"\\d{4}((([0][1,3-9]|[1][0-2]|[1-9])([0-2]\\d|[3][0,1]|[1-9]))|((02|2)(([1-9])|[0-2]\\d)))([0,1]\\d|[2][0-3])([0-5]\\d|\\d)([0-5]\\d|\\d)\\d{1,3}",
                    DATE_TIME_PATTERN_YYYY_MM_DD_HH_MM_SS_SSS},
            {"\\d{4}((([0][1,3-9]|[1][0-2]|[1-9])([0-2]\\d|[3][0,1]|[1-9]))|((02|2)(([1-9])|[0-2]\\d)))",
                    DATE_TIME_PATTERN_YYYY_MM_DD}
    };

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date    日期
     * @param pattern 格式，如：DateUtils.DATE_TIME_PATTERN
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    /**
     * 字符串转换成日期
     *
     * @param strDate 日期字符串
     * @param pattern 日期的格式，如：DateUtils.DATE_TIME_PATTERN
     */
    public static Date stringToDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }

        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
        return fmt.parseLocalDateTime(strDate).toDate();
    }


    /**
     * 根据传入的日期格式字符串，获取日期的格式
     *
     * @return 秒
     */
    public static String getDateFormat(String date_str) {
        String style = null;
        if (org.springframework.util.StringUtils.isEmpty(date_str)) {
            return null;
        }
        boolean b = false;
        for (int i = 0; i < regularExp.length; i++) {
            b = date_str.matches(regularExp[i][0]);
            if (b) {
                style = regularExp[i][1];
            }
        }
        if (org.springframework.util.StringUtils.isEmpty(style)) {
            log.info("date_str:" + date_str);
            log.info("日期格式获取出错，未识别的日期格式");
        }
        return style;
    }

    /**
     * 转换为时间类型格式
     *
     * @param strDate 日期
     * @return
     */
    public static Date strToDate(String strDate) {
        try {
            String strType = getDateFormat(strDate);
            SimpleDateFormat sf = new SimpleDateFormat(strType);
            return new Date((sf.parse(strDate).getTime()));
        } catch (Exception e) {
            return null;
        }
    }

    public static long strToTime(String timeStr) {
        Date time = strToDate(timeStr);
        return time.getTime() / 1000;
    }

    /**
     * 根据周数，获取开始日期、结束日期
     *
     * @param week 周期  0本周，-1上周，-2上上周，1下周，2下下周
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getWeekStartAndEnd(int week) {
        DateTime dateTime = new DateTime();
        LocalDate date = new LocalDate(dateTime.plusWeeks(week));

        date = date.dayOfWeek().withMinimumValue();
        Date beginDate = date.toDate();
        Date endDate = date.plusDays(6).toDate();
        return new Date[]{beginDate, endDate};
    }

    /**
     * 根据时间，获取当前日期的开始日期、结束日期
     *
     * @param dt 时间
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getWeekStartAndEndByDate(Date dt) {
        LocalDate date = new LocalDate(dt);

        date = date.dayOfWeek().withMinimumValue();
        Date beginDate = date.toDate();
        Date endDate = date.plusDays(6).toDate();
        return new Date[]{beginDate, endDate};
    }

    /**
     * 根据时间，获取月开始日期、结束日期
     *
     * @param month 月 0本月，-1上月，-2上上月，1下月，2下下月
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getMonthStartAndEnd(int month) {
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.MONTH, month);
        //设置为1号,当前日期既为本月第一天
        c.set(Calendar.DAY_OF_MONTH, 1);
        //将小时至0
        c.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        c.set(Calendar.MINUTE, 0);
        //将秒至0
        c.set(Calendar.SECOND, 0);
        //将毫秒至0
        c.set(Calendar.MILLISECOND, 0);
        Date date1 = c.getTime();
        c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.MONTH, month);

        //设置为当月最后一天
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        //将小时至23
        c.set(Calendar.HOUR_OF_DAY, 23);
        //将分钟至59
        c.set(Calendar.MINUTE, 59);
        //将秒至59
        c.set(Calendar.SECOND, 59);
        //将毫秒至999
        c.set(Calendar.MILLISECOND, 999);
        Date date2 = c.getTime();
        return new Date[]{date1, date2};
    }

    /**
     * 根据时间，获取月开始日期、结束日期
     *
     * @param date
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getMonthStartAndEnd(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        //设置为1号,当前日期既为本月第一天
        c.set(Calendar.DAY_OF_MONTH, 1);
        //将小时至0
        c.set(Calendar.HOUR_OF_DAY, 0);
        //将分钟至0
        c.set(Calendar.MINUTE, 0);
        //将秒至0
        c.set(Calendar.SECOND, 0);
        //将毫秒至0
        c.set(Calendar.MILLISECOND, 0);
        Date date1 = c.getTime();
        c = Calendar.getInstance();
        c.setTime(date);

        //设置为当月最后一天
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
        //将小时至23
        c.set(Calendar.HOUR_OF_DAY, 23);
        //将分钟至59
        c.set(Calendar.MINUTE, 59);
        //将秒至59
        c.set(Calendar.SECOND, 59);
        //将毫秒至999
        c.set(Calendar.MILLISECOND, 999);
        Date date2 = c.getTime();
        return new Date[]{date1, date2};
    }

    /**
     * 对日期的【秒】进行加/减
     *
     * @param date    日期
     * @param seconds 秒数，负数为减
     * @return 加/减几秒后的日期
     */
    public static Date addDateSeconds(Date date, int seconds) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusSeconds(seconds).toDate();
    }

    /**
     * 对日期的【分钟】进行加/减
     *
     * @param date    日期
     * @param minutes 分钟数，负数为减
     * @return 加/减几分钟后的日期
     */
    public static Date addDateMinutes(Date date, int minutes) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMinutes(minutes).toDate();
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param date  日期
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(Date date, int hours) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusHours(hours).toDate();
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param date 日期
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(Date date, int days) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusDays(days).toDate();
    }

    /**
     * 对日期的【周】进行加/减
     *
     * @param date  日期
     * @param weeks 周数，负数为减
     * @return 加/减几周后的日期
     */
    public static Date addDateWeeks(Date date, int weeks) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusWeeks(weeks).toDate();
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(Date date, int months) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMonths(months).toDate();
    }

    /**
     * 对日期的【年】进行加/减
     *
     * @param date  日期
     * @param years 年数，负数为减
     * @return 加/减几年后的日期
     */
    public static Date addDateYears(Date date, int years) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusYears(years).toDate();
    }

    /**
     * Date转LocalDate
     *
     * @param date
     */
    public static java.time.LocalDate date2LocalDate(Date date) {
        if (null == date) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * 日期比较（时分秒不参与）
     *
     * @param date1
     * @param date2
     * @return 负数  0  正数    null 数据传入有误
     */
    public static Integer compareDate(Object date1, Object date2) {
        if (date1 instanceof Date) {
            date1 = date2LocalDate((Date) date1);
        }
        if (date2 instanceof Date) {
            date2 = date2LocalDate((Date) date2);
        }
        if (date1 instanceof java.time.LocalDate && date2 instanceof java.time.LocalDate) {
            return ((java.time.LocalDate) date1).compareTo((java.time.LocalDate) date2);
        } else {
            return null;
        }
    }

    /**
     * 将当前传入时间的时分秒置零
     *
     * @param dateTime
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date dateTimeToDate(Date dateTime) {
        Calendar c = Calendar.getInstance();
        c.setTime(dateTime);
        c.set(Calendar.HOUR, 0);
        //将分钟至0
        c.set(Calendar.MINUTE, 0);
        //将秒至0
        c.set(Calendar.SECOND, 0);
        //将毫秒至0
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }


    /**
     * 时分秒比较大小
     *
     * @param now
     * @param compTime
     * @return 负数  0  正数    null 数据传入有误
     */
    public static Integer compTime(String now, String compTime) {
        try {
            if (now.indexOf(":") < 0 || now.indexOf(":") < 0) {
                return null;
            } else {
                String[] array1 = now.split(":");
                int total1 = Integer.valueOf(array1[0]) * 3600 + Integer.valueOf(array1[1]) * 60 + Integer.valueOf(array1[2]);
                String[] array2 = compTime.split(":");
                int total2 = Integer.valueOf(array2[0]) * 3600 + Integer.valueOf(array2[1]) * 60 + Integer.valueOf(array2[2]);
                return total1 - total2 > 0 ? 1 : total1 - total2 == 0 ? 0 : -1;
            }
        } catch (NumberFormatException e) {
            // TODO Auto-generated catch block
            return null;
        }
    }

    public static void main(String[] args) {
//        Date now = new Date();
//        String nowDate = DateUtils.format(new Date(), DateUtils.DATE_PATTERN);
//        String nowTime = DateUtils.format(new Date(), "HH:mm:ss");
//        System.out.println(DateUtils.compareDate(now, DateUtils.strToDate("2021-08-10")));
//        System.out.println(DateUtils.compareDate(now, DateUtils.strToDate("2021-08-12")));
//        System.out.println(DateUtils.compTime(nowTime, "20:00:00"));
//        System.out.println(DateUtils.compTime(nowTime, "22:00:00"));
//        System.out.println((-3 & -4) == 0);
        LocalDate localdate = LocalDate.parse("2022-04-21");
        LocalTime nowTime = LocalTime.now();
        System.out.println(localdate);
        System.out.println(nowTime);
        LocalDateTime ldt2 = LocalDateTime.now();

        LocalDateTime parse = LocalDateTime.parse(localdate + "T" + nowTime);
        Date date = Date.from( parse.atZone( ZoneId.systemDefault()).toInstant());
        System.out.println(date);
        System.out.println(parse);
        System.out.println(ldt2);
    }



    public static boolean compare(Date nowTime,String startDate,String endDate,SimpleDateFormat sdf){
        return compare(nowTime, startDate, endDate, sdf,true);
    }

    /**
     * 判断时间是否在指定日期范围内
     *
     * @param nowTime
     * @param startDate
     * @param endDate
     * @return
     */
    public static boolean compare(Date nowTime,Date startDate,Date endDate){
        if (nowTime==null){
            return false;
        }
        if (startDate==null&&endDate==null){
            return false;
        }
        long now = nowTime.getTime();
        /*判断是否在指定日期之后*/
        if (startDate!=null){
            long start = startDate.getTime();
            if (start>now){
                return false;
            }
        }
        /*判断是否在指定日期之前*/
        if (endDate!=null){
            long end = endDate.getTime();
            if (end<now){
                return false;
            }
        }
        return true;
    }

    /**
     * 判断nowTime时间是否在时间范围之内
     * @param nowTime
     * @param startDate
     * @param endDate
     * @param sdf
     * @param bool  true为日期，false为小时
     * @return
     */
    public static boolean compare(Date nowTime,String startDate,String endDate,SimpleDateFormat sdf,boolean bool){

        try {
            Date startTime = sdf.parse(startDate);
            Date endTime = sdf.parse(endDate);

            if (nowTime.getTime() == startTime.getTime()
                    || nowTime.getTime() == endTime.getTime()) {
                return true;
            }

            Calendar date = Calendar.getInstance();
            date.setTime(nowTime);

            Calendar begin = Calendar.getInstance();
            begin.setTime(startTime);

            Calendar end = Calendar.getInstance();
            end.setTime(endTime);

            if (date.after(begin) && date.before(end)) {
                return true;
            } else {
                if (bool&&(isSameDay(date,begin)||isSameDay(date,end))){
                    return true;
                }
                return false;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static boolean isSameDay(final Calendar cal1, final Calendar cal2){
        return cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
                cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
    }

    public static boolean compareTime(Date now,String startDate,String endDate,SimpleDateFormat sdf){

        try {

            String date1 = sdf.format(now);
            Date nowTime=sdf.parse(date1);
            return compare(nowTime,startDate,endDate,sdf,false);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获得指定年月的天数
     * @param year
     * @param month
     * @return
     */
    public static int getDayNumberOfMonth(int year,int month){
        java.time.LocalDate localDate = java.time.LocalDate.ofYearDay(year,month);
        return localDate.lengthOfMonth();
    }

    /**
     * 获得指定年月的开始日期
     * @param year
     * @param month
     * @return
     */
    public static int getStartDayOfMonth(int year,int month,String startDate){
        java.time.LocalDate start = java.time.LocalDate.parse(startDate);
        int monthValue = start.getMonthValue();
        int ye = start.getYear();
        if (ye<year || monthValue<month){
            return 1;
        }
        return start.getDayOfMonth();
    }

    /**
     * 获得指定年月的结束日期
     * @param year
     * @param month
     * @param endDate
     * @return
     */
    public static int getEndDayOfMonth(int year,int month,String endDate){
        java.time.LocalDate start = java.time.LocalDate.parse(endDate);
        int monthValue = start.getMonthValue();
        int ye = start.getYear();
        if (ye>year || monthValue>month){
            java.time.LocalDate localDate = java.time.LocalDate.of(year,month,1);
            return localDate.lengthOfMonth();
        }
        return start.getDayOfMonth();
    }


    /**
     * 获得不连续的所有日期，指定周几
     * @param year
     * @param month
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> getDayOfMonthFilterWeek(int year,int month,String startDate,String endDate,String week){
        /*1.获得开始日期*/
        int start = getStartDayOfMonth(year, month, startDate);
        /*2.获得结束日期*/
        int endDayOfMonth = getEndDayOfMonth(year, month, endDate);

        String[] split = week.split(",");
        List<String> strings = Arrays.asList(split);
        List<String> list =new ArrayList<>();
        java.time.LocalDate date=null;
        for (int i=start;i<=endDayOfMonth;i++){
            date = java.time.LocalDate.of(year, month, i);
            String wee = String.valueOf(date.getDayOfWeek().getValue());
            boolean bool = strings.contains(wee);
            if (bool){
                list.add(String.valueOf(i));
            }
        }
        return list;
    }



}
